// Tree.h: interface for the Tree class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_TREE_H__BFEBD167_5229_45BD_85F0_222037D604E6__INCLUDED_)
#define AFX_TREE_H__BFEBD167_5229_45BD_85F0_222037D604E6__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "PersistentObject.h"
#include <vector>
#include "PDMSClassRegister.h"
#include "RegisterObject.h"

namespace PDMS
{
	namespace PDMSDBIF
	{
		class PersistRegBase;
	}
	namespace PDMSFrame
	{
		class Hash;
		class UeDbObject;
		typedef UeDbObject Tree;

		class DllExport UeDbObject : public PersistentObject  
		{
			UE_DECLARE_DYNAMIC( UeDbObject );

			friend class Hash;
			friend class HashIterator;
			friend class PDMSDBIF::PersistRegBase;
		private:
			typedef std::vector< UeObjectId > SubTreeVector;

		public:
			class DllExport iterator {
				friend class UeDbObject;
			private:
				iterator( const Tree* pTree, BOOL atBeginning, BOOL skipDeleted );

			public:
				iterator() : m_pTree(0),m_it(0){
				}
				iterator( const iterator& it ) {
					m_pTree = it.m_pTree;
					m_it = it.m_it;
				}
				~iterator(){}

			public:
				iterator operator++(int);
				iterator& operator=( const iterator& it ){
					if (this == &it)
					{
						return *this;
					}

					m_pTree = it.m_pTree;
					m_it = it.m_it;

					return *this;
				}

				BOOL end(){
					return m_pTree == NULL || m_it == m_pTree->m_arSubTree.end();
				}

				UESoft::ErrorStatus Get( Tree*& pTree,
					UeDb::OpenModel om = UeDb::eForWrite );
			private:
				const UeDbObject* m_pTree;
				SubTreeVector::const_iterator m_it;
				BOOL m_skipDeleted;
			};
			typedef PDMSClassRegisterInfo RegisterInfo;
			typedef UeDbObject Style;
			
			friend class iterator;
		public:
			UeDbObject();
			UeDbObject( const UeDbObject& obj );
			virtual ~UeDbObject();
			
		public:
			virtual UESoft::ErrorStatus Add( Tree* pTree );
			void RemoveAll();
			UESoft::ErrorStatus SetParam();
			virtual Persistable* Clone() = 0;
			virtual BOOL IsLegalParent( UeDbObject* pParent ) = 0;
			virtual const StdString& ClassID() const = 0;
			virtual UESoft::ErrorStatus SetDelete();

		public:
			INT SubTreeCount() {
				AssertReadEnable();
				return m_arSubTree.size();
			}
			const StdString& Name() const {
				AssertReadEnable();
				return m_strName;
			}

			void Name( const StdString& strName );

			void HashModel( Hash* pHash ) {
				AssertWriteEnable();
				ASSERT( pHash );
				m_pHash = pHash;
			}

			Hash* HashModel() const {
				AssertReadEnable();
				return m_pHash;
			}

			virtual UESoft::ErrorStatus Parent( UeDbObject*& pObj, UeDb::OpenModel om = UeDb::eForWrite ) const;

			iterator Iterator(BOOL atBeginning = TRUE, BOOL skipDeleted = TRUE ) const {
				AssertReadEnable();
				return iterator( this, atBeginning, skipDeleted );
			}

			const StdString& Description() const {
				return m_strDescription;
			}

			void Description( const StdString& strDesc ) {
				m_strDescription = strDesc;
			}
			
		private:
			void Parent( const UeObjectId& id ) {
				AssertWriteEnable();
				OwnerId( id );
			}

			void AddSonId( const UeObjectId& id ) {
				m_arSubTree.push_back( id );
			}

			StdString AutoName() const;
		private:
			SubTreeVector m_arSubTree;
			StdString m_strName;
			Hash* m_pHash;
			StdString m_strDescription;
			
		protected:
		};
	}
}

#define UE_PDMSCLASS_DEFINE( class_name )\
	DECLARE_DYNAMIC_CREATE( class_name )\
	public:\
	virtual const StdString& ClassID() const;\
	private:\
	static const StdString m_strClassID;

#define UE_PDMSCLASS_IMPLEMENT( class_name, base_class, class_id )\
	IMPLEMENT_DYNAMIC_CREATE( class_name, base_class, #class_name )\
	const StdString class_name::m_strClassID( class_id );\
	const StdString& class_name::ClassID() const\
	{\
		return class_name::m_strClassID;\
	}		

#define UE_PDMSCLASS_REGKEY( class_name ) #class_name
#define UE_PDMSCLASS_ID( class_id ) #class_id
#endif // !defined(AFX_TREE_H__BFEBD167_5229_45BD_85F0_222037D604E6__INCLUDED_)
